﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Threading;
using System.IO;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace Win7ThemeEditor
{
    /// <summary>
    /// 图片加载进度事件
    /// </summary>
    /// <param name="sender">加载者对象</param>
    /// <param name="byteLoaded">已经加载的byte数</param>
    /// <param name="byteTotile">总长度</param>
    public delegate void LoadProgress(ImageThreadLoad sender,long byteLoaded,long byteTotile);
 
    /// <summary>
    /// 图片加载完成
    /// </summary>
    /// <param name="sender">加载者对象</param>
    public delegate void LoadComplete(ImageThreadLoad sender);
 
    /// <summary>
    /// 加载状态枚举
    /// </summary>
    public enum ImageLoadStatus {
        /// <summary>
        /// 已准备好，可以加载图片
        /// </summary>
        Ready,
        /// <summary>
        /// 图片加载中
        /// </summary>
        Progress,
        /// <summary>
        /// 图片已经加载完成
        /// </summary>
        Complete
    }
 
    /// <summary>
    /// 异步图片加载类
    /// </summary>
    public class ImageThreadLoad : DependencyObject
    {
        /// <summary>
        /// 错误消息，在结束时间中如果没获取到对象。请查看该对象以了解错误原因
        /// </summary>
        public String ErrorMessage;
 
        /// <summary>
        /// 当前加载的图片原始地址
        /// </summary>
        public String ImagePath;
 
        /// <summary>
        /// 缩略图的限制大小
        /// </summary>
        public Size MaxSize = new Size(100,100);
 
        /// <summary>
        /// 加载完成事件
        /// </summary>
        public event LoadComplete Complete;
 
        /// <summary>
        /// 加载进度事件
        /// </summary>
        public event LoadProgress Progress;
 
        public static DependencyProperty StatusProperty = DependencyProperty.Register("Status", //属性名称
           typeof(ImageLoadStatus),
            //属性类型
           typeof(ImageThreadLoad),
            //该属性所有者，即将该属性注册到那个类上
           new PropertyMetadata(ImageLoadStatus.Ready)); //属性默认值
        public ImageLoadStatus Status { get { return (ImageLoadStatus)GetValue(StatusProperty); } set { SetValue(StatusProperty, value); } }
        //public ImageLoadStatus Status { get; set ; } ;
 
        public static DependencyProperty LengthProperty = DependencyProperty.Register("Length", //属性名称
           typeof(long),
            //属性类型
           typeof(ImageThreadLoad),
            //该属性所有者，即将该属性注册到那个类上
           new PropertyMetadata(0L)); //属性默认值
        public long Length { get { return (long)GetValue(LengthProperty); } set { SetValue(LengthProperty, value); } }
 
        public static DependencyProperty ByteLoadedProperty = DependencyProperty.Register("ByteLoaded", //属性名称
           typeof(long),
            //属性类型
           typeof(ImageThreadLoad),
            //该属性所有者，即将该属性注册到那个类上
           new PropertyMetadata(0L)); //属性默认值
        public long ByteLoaded { get { return (long)GetValue(ByteLoadedProperty); } set { SetValue(ByteLoadedProperty, value); } }
 
        public ImageThreadLoad() {
            thread = new Thread(new ThreadStart(runLoad));
            Status = ImageLoadStatus.Ready;
        }
 
        MemoryStream ms = null;//图像文件的内存流
        Thread thread = null;//异步进程
 
        /// <summary>
        /// 获取用于显示的 BitmapImage 对象，原始尺寸。
        /// </summary>
        public BitmapImage Image
        {
            get
            {
 
                if (ms == null || Status != ImageLoadStatus.Complete)
                {
                    return null;
                }
                BitmapImage BI = null;
                lock (ms)
                {
                    BI = new BitmapImage();
                    ms.Seek(0, SeekOrigin.Begin);
 
                    BI.BeginInit();
                    BI.StreamSource = ms;
                    BI.EndInit();
                }
                return BI;
            }
        }
 
        /// <summary>
        /// 获取缩略图，默认不大于100，如要设置尺寸请在获取前设置MaxSize属性
        /// </summary>
        public BitmapImage ThumbnaiImage
        {
            get
            {

                if (ms == null || Status != ImageLoadStatus.Complete)
                {
                    return null;
                }
                BitmapImage BI = null;
                lock (ms)
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    System.Drawing.Image fullSizeImg = System.Drawing.Image.FromStream(ms);
 
                    int filewidth = 0;
                    int fileheight = 0;
 
                    if (fullSizeImg.Height <= fullSizeImg.Width)
                    {
                        filewidth = (int)MaxSize.Width;
                        fileheight = fullSizeImg.Height /(fullSizeImg.Width / (int)MaxSize.Width) ;
                    }
                    else
                    {
                        fileheight = (int)MaxSize.Height;
                        filewidth = fullSizeImg.Width / (fullSizeImg.Height / (int)MaxSize.Height);
                    }
 
                    System.Drawing.Image nimag = fullSizeImg.GetThumbnailImage(filewidth, fileheight,null,System.IntPtr.Zero);
                    BI = new BitmapImage();
 
                    System.IO.MemoryStream tms = new System.IO.MemoryStream();
                    nimag.Save(tms, System.Drawing.Imaging.ImageFormat.Png);// 格式自处理,这里用 bitmap
                    // 下行,初始一个 ImageSource 作为 myImage 的Source
                    nimag.Dispose();
                    fullSizeImg.Dispose();
 
                    BI.BeginInit();
                    BI.StreamSource = tms;
                    BI.EndInit();
                }
 
                return BI;
            }
        }
 
        /// <summary>
        /// 清除所有资源占用并销毁线程内存流等对象,解除事件绑定。
        /// </summary>
        public void Destroy() {
            if (thread != null && thread.IsAlive)
            {
                thread.Abort();
            }
            if (ms != null) {
                ms.Close();
                ms = null;
            }
 
            if (Complete != null) {
                Delegate[] dlist = Complete.GetInvocationList();
                foreach (Delegate d in dlist) {
                    this.Complete -= (LoadComplete)d;
                }
            }
 
            if (Progress != null)
            {
                Delegate[] dlist = Progress.GetInvocationList();
                foreach (Delegate d in dlist)
                {
                    this.Progress -= (LoadProgress)d;
                }
            }
        }
 
        /// <summary>
        /// 加载指定本地图片。
        /// </summary>
        /// <param name="path">本地地址，相对或绝对地址</param>
        public void LoadImage(String path) {
            ImagePath = path;
            FileInfo fileinfo = new FileInfo(path);
            if (fileinfo.Exists)
            {
                Length = fileinfo.Length;
 
                if (Status == ImageLoadStatus.Ready)
                {
                    Status = ImageLoadStatus.Progress;
                    thread.Start();
                }
                else if (Status == ImageLoadStatus.Complete)
                {
                    //sendComplete();
                    Application.Current.Dispatcher.
                    BeginInvoke(DispatcherPriority.
                    Normal, (ThreadStart)delegate()
                    { sendComplete(); });
                }
            }
            else {
                ErrorMessage = "文件不存在！";
                Application.Current.Dispatcher.
                    BeginInvoke(DispatcherPriority.
                    Normal, (ThreadStart)delegate()
                    { sendComplete(); });
            }
 
        }
 
        /// <summary>
        /// 触发完成事件。完成不一定是加载成功，发生错误而失败也会触发完成事件。
        /// 具体查看ErrorMessage来获取错误信息
        /// </summary>
        private void sendComplete()
        {
            Status = ImageLoadStatus.Complete;
            if (Complete != null) {
                Complete.Invoke(this);
            }
        }
 
        void runLoad()
        {
            ms = new MemoryStream();
            FileStream fs = new FileStream(ImagePath, FileMode.Open);
            byte[] buff = new byte[2048*30];
            long size = 0;
            int readCount = 0;
            while ((readCount = fs.Read(buff, 0, buff.Length)) != 0)
            {
                size += readCount;
 
               // Console.WriteLine("Read:" + readCount + ",All Size:" + size);
                ms.Write(buff, 0, readCount);
                Thread.Sleep(10);
                try
                {
                    Application.Current.Dispatcher.
                        BeginInvoke(DispatcherPriority.
                        Normal, (ThreadStart)delegate()
                        { sendProgress(size); });
                }
                catch (Exception ex) {
                    //
                }
 
            }
 
            try
            {
                Application.Current.Dispatcher.
                    BeginInvoke(DispatcherPriority.
                    Normal, (ThreadStart)delegate()
                    { sendComplete(); });
            }
            catch (Exception ex)
            {
                //
            }
        }
 
        /// <summary>
        /// 发送当前的进度
        /// </summary>
        /// <param name="size"></param>
        private void sendProgress(long size)
        {
            ByteLoaded = size;
            if (Progress != null) {
                Progress.Invoke(this,ByteLoaded,Length);
            }
        }
    }
}
